#include <CoOS.h>			                 /*!< CoOS header file            */
#include <stdio.h>
#include "NUC123.h"

#define DH11_DECODE_NONE	0
#define DH11_DECODE_WS	1		//wait start
#define DH11_DECODE_S		2		//start
#define DH11_DECODE_BIT	3
#define DH11_DECODE_DONE	4
#define DH11_DECODE_FAIL	0xFF

#define INRANG(_i, _t, _r)	(((_i <= _t + _r) && (_i >= _t - _r))? TRUE:FALSE)

U8 u8DecodeState = DH11_DECODE_NONE;
U8 u8BitCnt = 0;
U8 au8Data[5];

void GPB5_IRQ(void)
{
	U32 plus;
	/* To check if PB.5 interrupt occurred */
	if(GPIO_GET_INT_FLAG(PB, BIT5))
	{
		GPIO_CLR_INT_FLAG(PB, BIT5);
		switch(u8DecodeState)
		{
			case DH11_DECODE_WS:
				u8DecodeState = DH11_DECODE_S;
				TIMER_Start(TIMER2);
				break;
			case DH11_DECODE_S:
				plus = TIMER_GetCounter(TIMER2);					
				if(INRANG(plus, 160, 40))				
				{
					TIMER_Reset(TIMER2);
					u8BitCnt = 0;
					u8DecodeState = DH11_DECODE_BIT;	
					memset(au8Data, 0, 5);
				}
				else
				{
					TIMER_Stop(TIMER2);
					u8DecodeState = DH11_DECODE_NONE;	
					printf("Exit DH11_DECODE_S %d\n", plus);
				}
				break;
			case DH11_DECODE_BIT:
				plus = TIMER_GetCounter(TIMER2);	
				if(INRANG(plus, 120, 10))
				{
					//bit 1
					TIMER_Reset(TIMER2);
					au8Data[u8BitCnt>>3] |= 1<<(7-(u8BitCnt%8) );
					u8BitCnt++;
					u8DecodeState = DH11_DECODE_BIT;	
				}
				else if(INRANG(plus, 80, 10))
				{
					//bit 0
					TIMER_Reset(TIMER2);
					u8BitCnt ++;
					u8DecodeState = DH11_DECODE_BIT;							
				}
				else
				{
					TIMER_Stop(TIMER2);
					u8DecodeState = DH11_DECODE_NONE;	
					printf("Exit DH11_DECODE_BIT %d\n", plus);
				}

				if(u8BitCnt == 40)
				{
					if(au8Data[4] == au8Data[0]+au8Data[1]+au8Data[2]+au8Data[3])
					{
						u8DecodeState = DH11_DECODE_DONE;							
					}
					else
					{
						u8DecodeState = DH11_DECODE_FAIL;							
					}

					TIMER_Stop(TIMER2);
				}
				break;
		}
		
	}
}


void DH11_Init(void)
{
	GPIO_SetMode(PB, BIT5, GPIO_PMD_QUASI);
	PB5 = 1;
}

void DH11_Trigger(void)
{	
	PB5 = 0;
	CoTickDelay(18);

	TIMER_Open(TIMER2, TIMER_ONESHOT_MODE, 1);
	TIMER_ClearIntFlag(TIMER2);
	TIMER_ClearWakeupFlag(TIMER2);
	
	TIMER_SET_PRESCALE_VALUE(TIMER2, 11);
	TIMER_SET_CMP_VALUE(TIMER2, 1000000);
	
	GPIO_EnableInt(PB, 5, GPIO_INT_FALLING);
	NVIC_EnableIRQ(GPAB_IRQn);
	u8DecodeState = DH11_DECODE_WS;
	PB5 = 1;
}

BOOL DH11_GetEnv(U8 *pu8T, U8 *puD)
{
	*pu8T = au8Data[2];
	*puD = au8Data[0];
	if(u8DecodeState != DH11_DECODE_DONE)
	{
		return FALSE;
	}

	return TRUE;
}

